#include <stdio.h>
#include <inttypes.h>
#include "esp_log.h"
#include "esp_camera.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "esp_http_server.h"
#include "esp_wifi.h"

// 定义日志标签
static const char *TAG = "ESP32-S3-CAM";

// Wi-Fi配置
#define WIFI_SSID      "liu"
#define WIFI_PASSWORD  "12345678"

// ESP32-S3-CAM引脚定义
#define CAM_PIN_PWDN     -1
#define CAM_PIN_RESET    -1
#define CAM_PIN_VSYNC    6
#define CAM_PIN_HREF     7
#define CAM_PIN_PCLK     13
#define CAM_PIN_XCLK     15
#define CAM_PIN_SIOD     4
#define CAM_PIN_SIOC     5
#define CAM_PIN_D0       11
#define CAM_PIN_D1       9
#define CAM_PIN_D2       8
#define CAM_PIN_D3       10
#define CAM_PIN_D4       12
#define CAM_PIN_D5       18
#define CAM_PIN_D6       17
#define CAM_PIN_D7       16

// HTTP服务器句柄
static httpd_handle_t server = NULL;

// 事件组用于Wi-Fi连接状态
static EventGroupHandle_t wifi_event_group;
const int WIFI_CONNECTED_BIT = BIT0;

// Wi-Fi事件处理程序
static void event_handler(void* arg, esp_event_base_t event_base, 
                          int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT);
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "获得IP地址: " IPSTR, IP2STR(&event->ip_info.ip));
        xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
    }
}

// 初始化Wi-Fi
static void wifi_init(void)
{
    ESP_LOGI(TAG, "初始化Wi-Fi...");
    
    // 创建事件组
    wifi_event_group = xEventGroupCreate();
    
    // 初始化TCP/IP栈和事件循环
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *netif = esp_netif_create_default_wifi_sta();
    assert(netif);
    
    // 注册事件处理程序
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
    
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    
    // 配置Wi-Fi
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASSWORD,
        },
    };
    
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_start());
    
    ESP_LOGI(TAG, "Wi-Fi初始化完成，正在连接至: %s", WIFI_SSID);
}

// 等待Wi-Fi连接
static void wait_for_wifi_connection(void)
{
    ESP_LOGI(TAG, "等待Wi-Fi连接...");
    
    // 等待连接成功
    EventBits_t bits = xEventGroupWaitBits(wifi_event_group, 
        WIFI_CONNECTED_BIT,
        pdFALSE,
        pdTRUE,
        portMAX_DELAY);
    
    if (bits & WIFI_CONNECTED_BIT) {
        ESP_LOGI(TAG, "Wi-Fi已连接");
    } else {
        ESP_LOGE(TAG, "Wi-Fi连接失败");
    }
}

// 处理根URL请求
static esp_err_t index_handler(httpd_req_t *req)
{
    ESP_LOGI(TAG, "收到根页面请求");
    
    const char *html = "<!DOCTYPE html>"
                       "<html>"
                       "<head><title>ESP32-CAM</title></head>"
                       "<body>"
                       "<h1>ESP32-CAM 图像查看器</h1>"
                       "<p><a href=\"/image\">查看最新图像</a></p>"
                       "</body>"
                       "</html>";
    
    httpd_resp_set_type(req, "text/html");
    return httpd_resp_send(req, html, strlen(html));
}

// 处理图像请求
static esp_err_t image_handler(httpd_req_t *req)
{
    ESP_LOGI(TAG, "收到图像请求");
    
    // 获取一帧图像
    camera_fb_t *fb = esp_camera_fb_get();
    if (!fb) {
        ESP_LOGE(TAG, "获取帧缓冲区失败");
        httpd_resp_send_500(req);
        return ESP_FAIL;
    }
    
    // 设置HTTP响应头
    httpd_resp_set_type(req, "image/jpeg");
    httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=image.jpg");
    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
    
    // 发送图像数据
    esp_err_t res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
    
    // 释放帧缓冲区
    esp_camera_fb_return(fb);
    
    ESP_LOGI(TAG, "图像已发送，大小: %d字节", fb->len);
    return res;
}

// 启动Web服务器
static void start_webserver(void)
{
    ESP_LOGI(TAG, "启动Web服务器...");
    
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.server_port = 80;
    config.ctrl_port = 32768;
    config.max_open_sockets = 3;
    
    // 启动HTTP服务器
    if (httpd_start(&server, &config) == ESP_OK) {
        // 注册URI处理程序
        httpd_uri_t index_uri = {
            .uri = "/",
            .method = HTTP_GET,
            .handler = index_handler,
            .user_ctx = NULL
        };
        
        httpd_uri_t image_uri = {
            .uri = "/image",
            .method = HTTP_GET,
            .handler = image_handler,
            .user_ctx = NULL
        };
        
        httpd_register_uri_handler(server, &index_uri);
        httpd_register_uri_handler(server, &image_uri);
        
        ESP_LOGI(TAG, "Web服务器已启动，端口: %d", config.server_port);
    } else {
        ESP_LOGE(TAG, "启动Web服务器失败");
    }
}

// 初始化摄像头
esp_err_t init_camera(void)
{
    ESP_LOGI(TAG, "初始化摄像头...");
    
    camera_config_t camera_config = {
        .pin_pwdn = CAM_PIN_PWDN,
        .pin_reset = CAM_PIN_RESET,
        .pin_xclk = CAM_PIN_XCLK,
        .pin_sccb_sda = CAM_PIN_SIOD,
        .pin_sccb_scl = CAM_PIN_SIOC,
        
        .pin_d7 = CAM_PIN_D7,
        .pin_d6 = CAM_PIN_D6,
        .pin_d5 = CAM_PIN_D5,
        .pin_d4 = CAM_PIN_D4,
        .pin_d3 = CAM_PIN_D3,
        .pin_d2 = CAM_PIN_D2,
        .pin_d1 = CAM_PIN_D1,
        .pin_d0 = CAM_PIN_D0,
        .pin_vsync = CAM_PIN_VSYNC,
        .pin_href = CAM_PIN_HREF,
        .pin_pclk = CAM_PIN_PCLK,
        
        .xclk_freq_hz = 10000000,
        .ledc_timer = LEDC_TIMER_0,
        .ledc_channel = LEDC_CHANNEL_0,
        
        .pixel_format = PIXFORMAT_JPEG,
        .frame_size = FRAMESIZE_SVGA, // 800x600
        .jpeg_quality = 12,
        .fb_count = 1,
        .fb_location = CAMERA_FB_IN_DRAM, // 使用内部RAM
        .grab_mode = CAMERA_GRAB_LATEST,
    };
    
    // 初始化摄像头驱动
    esp_err_t err = esp_camera_init(&camera_config);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "摄像头初始化失败: 0x%" PRIx32, (uint32_t)err);
        return err;
    }
    
    // 获取摄像头传感器
    sensor_t *s = esp_camera_sensor_get();
    if (s == NULL) {
        ESP_LOGE(TAG, "获取摄像头传感器失败");
        return ESP_FAIL;
    }
    
    // 调整传感器设置
    s->set_vflip(s, 1);
    s->set_hmirror(s, 1);
    
    ESP_LOGI(TAG, "摄像头初始化成功");
    return ESP_OK;
}

void app_main(void)
{
    // 初始化NVS
    ESP_LOGI(TAG, "初始化NVS...");
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    
    // 初始化摄像头
    if (init_camera() != ESP_OK) {
        ESP_LOGE(TAG, "摄像头初始化失败，程序终止");
        return;
    }
    
    // 初始化Wi-Fi
    wifi_init();
    
    // 等待Wi-Fi连接
    wait_for_wifi_connection();
    
    // 启动Web服务器
    start_webserver();
    
    ESP_LOGI(TAG, "ESP32-S3-CAM应用程序已启动");
    ESP_LOGI(TAG, "请在浏览器中访问ESP32的IP地址查看图像");
}